<template>
<div class="experiment">
    <div class="e-left-box" v-show="!isFullScreen">
        <div class="e-tab">
            <div class="e-t-item" @click="handleTypeId(i)" :class="{'e-t-active':i===typeId}" v-for="(item, i) in tabList" :key="i">
                <i :class="`iconfont ${item.icon}`"></i>
                <span>{{item.name}}</span>
            </div>
        </div>
        <div class="exp-item-left">
            <component @empty="isEmptyExp=$event" @addTab="handleGetTabs" @updateTab="handleUpdateTab" @copyExp="handleCopyExp" @addExp="handleAddExp" :is="elList[typeId]"></component>
        </div>
    </div>
    <div class="exp-item-mid" :style="{width: getWith()}">
        <console-info></console-info>
        <div v-if="editableTabs.length > 0" class="loading-box-wrap" v-loading="canvasLoading">
            <el-tabs id="tabs" v-model="tabsValue" type="border-card" closable @tab-remove="handleTabRemove($event, true)" @tab-click="handleTabClick">
                <el-tab-pane v-for="item in editableTabs" :key="item.experimentId" :name="`${item.experimentId}`">
                    <template slot="label">
                        <i class="iconfont icon-moxing_shiyan"></i>
                        <span class="tab-name">{{item.experimentName}}</span>
                    </template>
                    <template v-if="`${tabsValue}` === `${experimentId}` && canvasInfo.nodes && `${tabsValue}` === `${item.experimentId}`">
                        <main-canvas @fullScreen="handleFullScreen" @clickNode="handleClickNode" @clickCanvas="formData.show=false"></main-canvas>
                    </template>
                </el-tab-pane>
            </el-tabs>
        </div>
        <div v-else class="empty-wrap">
            <img src="@/assets/img/noExp.png" class="no-exp"/>
            <span>当前没有打开的实验，您可以</span>
            <span>
                <span class="lianjie" @click="handleAddExp(null)">新增实验</span> 或
            <span class="lianjie" @click="setTypeId(0)">打开</span>已有实验
            </span>
        </div>
    </div>
    <div class="exp-item-right" :style="{width: rightIsShow ? '20%' : '0'}">
        <div class="toggle-btn" @click="rightIsShow = !rightIsShow">
            <i :class="`el-icon-arrow-${rightIsShow ? 'right' : 'left'}`"></i>
        </div>
        <div class="right-empty-box">
            <template v-if="experimentId">
                <edit-form v-show="rightActive === 0" :formData="formData" @update="handleUpdateTab"></edit-form>
            </template>
            <message-notice v-show="rightActive === 1"></message-notice>
        </div>
        <div class="sider-right-box">
            <div class="sider-right-box-text" :class="{'right-active': i === rightActive}" v-for="(item, i) in rightTabs" :key="i" @click="handleRightTabs(i)">
                <i :class="item.icon"></i>
                <span>{{item.name}}</span>
            </div>
        </div>
    </div>
    <add-exp v-if="addExpForm.show" :addForm="addExpForm" @save="handleSaveExpDialog" @getParentCatalogId="getParentCatalogId"></add-exp>
</div>
</template>

<script>
import {
    mapGetters,
    mapMutations
} from 'vuex'
import ExpList from './list/ExpList'
import DataList from './list/DataList'
import ComponentList from './list/ComponentList'
import ModelList from './list/ModelList'
import MainCanvas from './MainCanvas'
import EditForm from './editForm'
import AddExp from './AddExp'
import MessageNotice from './MessageNotice'
import ConsoleInfo from './consoleInfo'

export default {
    name: 'Experiment',
    components: {
        ConsoleInfo,
        ExpList,
        DataList,
        ComponentList,
        ModelList,
        MainCanvas,
        EditForm,
        AddExp,
        MessageNotice
    },
    data () {
        return {
            rightActive: 0,
            rightTabs: [
                { icon: 'iconfont icon-zujiancanshu', name: '组件参数' },
                { icon: 'iconfont icon-xiaoxitongzhi', name: '消息通知' }
            ],
            rightIsShow: true,
            clickTimer: null,
            isEmptyExp: false, // 如果实验列表为空则不显示右侧实验属性
            isCopy: false,
            addExpForm: {
                show: false,
                title: '新增实验',
                form: {
                    experimentName: null,
                    description: null,
                    catalogId: null
                }
            },
            tabsValue: '',
            elList: [ExpList, DataList, ComponentList, ModelList],
            formData: {
                show: false,
                data: {}
            },
            isFullScreen: false,
            tabList: [
                {
                    value: '0',
                    name: '实验',
                    icon: 'icon-shiyan'
                },
                {
                    value: '1',
                    name: '数据',
                    icon: 'icon-shuju'
                },
                {
                    value: '2',
                    name: '组件',
                    icon: 'icon-zujian'
                },
                {
                    value: '3',
                    name: '模型',
                    icon: 'icon-module-source-destination'
                }
            ]
        }
    },
    created () {
        this.init()
    },
    mounted () {
        // 禁止文字选择
        this.$el.onselectstart = e => {
            e.returnValue = false
        }
        this.setCanvasLoading(true)
    },
    computed: {
        ...mapGetters({
            canvasLoading: 'common/getCanvasLoading',
            projectId: 'common/getProjectId',
            typeId: 'common/getTypeId',
            experimentId: 'common/getExperimentId',
            canvasInfo: 'common/getCanvasInfo',
            editableTabs: 'common/getEditableTabs',
            clickNode: 'common/getClickNode',
            removeCanvasExp: 'common/getRemoveCanvasExp'
        })
    },
    watch: {
        removeCanvasExp (val) {
            this.handleTabRemove(val)
        },
        clickNode () {
            this.rightIsShow = true
        }
    },
    methods: {
        ...mapMutations({
            setCanvasLoading: 'common/setCanvasLoading',
            setNodeMap: 'common/setNodeMap',
            setLinkMap: 'common/setLinkMap',
            setTypeId: 'common/setTypeId',
            setCanvasInfo: 'common/setCanvasInfo',
            setNodePortMapper: 'common/setNodePortMapper',
            setCurrentExpInfo: 'common/setCurrentExpInfo',
            setExperimentId: 'common/setExperimentId',
            setNewExp: 'common/setNewExp',
            setShowNodeProp: 'common/setShowNodeProp',
            setEditableTabs: 'common/setEditableTabs'
        }),
        getParentCatalogId (val) {
            this.addExpForm.form.catalogId = val
        },
        handleRightTabs (i) {
            this.rightActive = i
        },
        getWith () {
            if (this.isFullScreen) {
                return this.rightIsShow ? '80%' : '100%'
            } else {
                return this.rightIsShow ? '60%' : '80%'
            }
        },
        handleFullScreen () {
            this.isFullScreen = !this.isFullScreen
            if (this.isFullScreen) {
                this.rightIsShow = false
            }
        },
        // 实验编辑器实验/数据/组件/模型，切换时候需要传给后端的id
        handleTypeId (i) {
            this.setTypeId(i)
        },
        // 新增实验
        handleAddExp (parentId) {
            this.isCopy = false
            this.addExpForm = {
                show: true,
                title: '新增实验',
                form: {
                    experimentName: null,
                    description: null,
                    catalogId: !parentId ? null : parentId
                }
            }
        },
        // 复制实验
        handleCopyExp (item) {
            this.isCopy = true
            const {
                experimentId,
                experimentName,
                description
            } = item
            this.addExpForm = {
                show: true,
                title: '复制实验',
                form: {
                    experimentName,
                    description,
                    experimentId
                }
            }
        },
        // 实验保存
        handleSaveExpDialog () {
            const {
                experimentName,
                description,
                catalogId
            } = this.addExpForm.form
            const params = {
                experimentId: this.isCopy ? this.addExpForm.form.experimentId : this.experimentId,
                projectId: this.projectId,
                experimentName,
                description,
                catalogId
            }
            let url = null
            if (this.isCopy) {
                url = '/experiment/copyExperiment'
            } else {
                url = '/experiment/createExperiment'
                delete params.experimentId
            }
            this.$post(url, params).then(res => {
                if (res) {
                    this.typeId !== 0 && this.setTypeId(0)
                    this.$message.success('保存成功')
                    this.addExpForm.show = false
                    setTimeout(() => {
                        this.setNewExp(res.experimentId)
                    }, 500)
                }
            })
        },
        // 打开实验列表里面某一个实验，如果该实验不存在就添加到画布上方的tab列表里面
        handleGetTabs (item) {
            let arr = this.editableTabs
            let flag = true
            const { experimentId } = item
            for (let i = 0; i < arr.length; i++) {
                if (arr[i].experimentId === experimentId) {
                    this.tabsValue = `${experimentId}`
                    flag = false
                    break
                }
            }
            if (flag) {
                // 如果打开的实验超过6个就关闭最后一个，再打开新加的实验
                arr.length > 5 ? this.handleTabRemove(arr[5].experimentId, true, item) : this.handleAddExpTab(item)
            } else {
                this.getInfo()
            }
        },
        // 添加实验tab
        handleAddExpTab (item) {
            const arr = this.editableTabs.concat(item)
            localStorage.setItem('editableTabs', JSON.stringify(arr))
            this.setEditableTabs(arr)
            this.$nextTick(() => {
                this.setExperimentId(item.experimentId)
                this.tabsValue = `${item.experimentId}`
                this.getInfo()
            })
        },
        // 初始化画布获取的数据（包含几个tab的数据）
        init () {
            const params = {
                projectId: this.projectId
            }
            this.$post('/experiment/queryOpenedExperiments', params).then(res => {
                if (res) {
                    const {
                        openExperiments
                    } = res
                    if (openExperiments.length > 0) {
                        let [item] = openExperiments.filter(v => v.openState === 1)
                        if (this.$isEmpty(item)) {
                            item = openExperiments[0]
                        }
                        this.tabsValue = item.experimentId + ''
                        this.setExperimentId(item.experimentId)
                        localStorage.setItem('editableTabs', JSON.stringify(openExperiments))
                        this.setEditableTabs(openExperiments)
                        this.getInfo()
                    } else {
                        this.setExperimentId('')
                        localStorage.setItem('editableTabs', JSON.stringify([]))
                        this.setEditableTabs([])
                    }
                }
            })
        },
        // 修改标题名字
        handleUpdateTab ({ experimentId, experimentName }) {
            let item = null
            let arr = this.editableTabs
            for (let i = 0; i < arr.length; i++) {
                if (arr[i].experimentId - 0 === experimentId - 0) {
                    arr[i].experimentName = experimentName
                    item = arr[i]
                    break
                }
            }
            if (item) {
                document.getElementById(`tab-${experimentId}`).getElementsByClassName('tab-name')[0].innerHTML = experimentName
            }
            localStorage.setItem('editableTabs', JSON.stringify(arr))
            this.setEditableTabs(arr)
        },
        handleTabClick (item) {
            if (this.tabsValue === `${this.experimentId}`) {
                return
            }
            this.setCanvasLoading(true)
            window.clearTimeout(this.clickTimer)
            this.clickTimer = setTimeout(() => {
                this.setExperimentId(item.name - 0)
                this.tabsValue = item.name
                this.getInfo()
                this.setShowNodeProp(false)
            }, 500)
        },
        // 获取当前实验下的画布信息
        getInfo () {
            const params = {
                projectId: this.projectId,
                experimentId: this.experimentId
            }
            this.$post('/experiment/getOutputAndInputPortsMatchTable', {
                projectId: this.projectId
            }).then((data) => {
                let nodePortMapper = {}
                for (let item of data) {
                    let matchTypes = {}
                    for (let subItem of item.matchInputPortTypes) {
                        matchTypes[subItem.type] = subItem
                    }
                    this.$set(nodePortMapper, item.type, matchTypes)
                }
                this.setNodePortMapper(nodePortMapper)
                this.$post('/experiment/queryExperimentGraph', params).then(res => {
                    if (res && params.experimentId === this.experimentId) {
                        res.isInit = false
                        res.experimentId = params.experimentId
                        const fn = (name, arr) => {
                            let res = {}
                            for (let i = 0; i < arr.length; i++) {
                                res[`${arr[i][name]}`] = arr[i]
                            }
                            return res
                        }
                        this.setNodeMap(fn('nodeId', res.nodes))
                        this.setLinkMap(fn('linkId', res.links))
                        this.setCanvasInfo(res)
                    } else {
                        this.setCanvasLoading(false)
                    }
                })
            })
            // 获取当前实验信息
            this.$post('/experiment/openExperiment', params).then(res => {
                res && this.setCurrentExpInfo(res)
                localStorage.setItem('experimentName', res.experimentName)
            }).catch(() => {})
        },
        // 删除画布的其中一个tab
        handleTabRemove (id, isTab, item) {
            if (id - 0 === this.tabsValue - 0) {
                this.setCanvasLoading(true)
            }
            let experimentId = id + ''
            let flag = false
            let arr = this.editableTabs
            if (arr.length > 0) {
                for (let i = 0; i < arr.length; i++) {
                    if (experimentId - 0 === arr[i].experimentId - 0) {
                        flag = true
                        break
                    }
                }
                if (flag) {
                    if (isTab) {
                        const params = {
                            projectId: this.projectId,
                            experimentId
                        }
                        this.$post('/experiment/closeExperiment', params).then(res => {
                            if (res) {
                                if (item) {
                                    const newArr = arr.filter(tab => experimentId !== `${tab.experimentId}`)
                                    localStorage.setItem('editableTabs', JSON.stringify(newArr))
                                    this.setEditableTabs(newArr)
                                    this.handleAddExpTab(item)
                                } else {
                                    this.nextTab(experimentId)
                                }
                            }
                        })
                    } else {
                        this.nextTab(experimentId)
                    }
                }
            }
        },
        nextTab (experimentId) {
            let tabs = this.editableTabs
            let activeId = this.tabsValue
            if (activeId === experimentId) {
                tabs.forEach((tab, i) => {
                    if (experimentId === `${tab.experimentId}`) {
                        let nextTab = tabs[i + 1] || tabs[i - 1]
                        if (nextTab) {
                            activeId = nextTab.experimentId
                        }
                    }
                })
            }
            this.tabsValue = `${activeId}`
            const newTabs = tabs.filter(tab => experimentId !== `${tab.experimentId}`)
            localStorage.setItem('editableTabs', JSON.stringify(newTabs))
            this.setEditableTabs(newTabs)
            // 删除一个tab需要重新加载当前的tab数据
            if (this.editableTabs.length > 0) {
                this.setExperimentId(activeId)
                this.getInfo()
            } else {
                this.setExperimentId(null)
            }
        },
        handleClickNode (item) {
            this.formData = {
                show: true,
                data: item
            }
        }
    },
    destroyed () {
        localStorage.removeItem('experimentID')
    }
}
</script>

<style lang="less">
.experiment {
    overflow: hidden;
    background: #f5f5f5;
    height: 100%;
    width: 100%;
    display: flex;
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    -khtml-user-select: none;
    user-select: none;

    #tabs {
        .icon-moxing_shiyan {
            margin-right: 3px;
        }

        .el-tabs__nav {
            display: flex;
        }

        .el-tabs__item {
            border-top: 2px solid #f5f5f5;
            width: 160px;
            border-right-color: #dcdfe6;
            text-overflow: ellipsis;
            white-space: nowrap;
            overflow: hidden;
            position: relative;

            .el-icon-close {
                position: absolute;
                top: 11px;
                right: 5px;
                width: 18px;
                height: 18px;
                line-height: 19px;
                text-align: center;
            }
        }
        .is-active {
            border-top: 2px solid #2680eb;
        }

        .tab-label {
            max-width: 180px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
    }

    .lianjie {
        cursor: pointer;
        color: #2680eb;
    }

    .empty-wrap {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;

        i {
            font-size: 100px;
            color: #2680eb;
        }

        span {
            line-height: 32px;
        }
    }

    .e-left-box {
        overflow: hidden;
        display: flex;
        z-index: 2;
        width: 20%;
    }

    .e-tab {
        overflow: hidden;
        height: 100%;
        width: 30px;
        background: #E6E6E6;

        .e-t-item {
            border-bottom: 1px solid #d9d9d9;
            border-left: 2px solid #E6E6E6;
            cursor: pointer;
            width: 100%;
            padding: 16px 0;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;

            i {
                font-size: 20px;
                color: #3a3a3a;
                margin-bottom: 5px;
            }

            span {
                white-space: pre-wrap;
                color: #3a3a3a;
                text-align: center;
                font-size: 16px;
            }
            &:hover {
                i, span {
                    color: #2680eb;
                }
            }
        }

        .e-t-active {
            border-left: 2px solid #2680eb;
            background: #f5f5f5;
            i,
            span {
                color: #2680eb !important;
            }
        }
    }
    .exp-item-left {
        overflow: hidden;
        font-size: 13px;
        width: 100%;
        height: 100%;
        .search-inpt {
            padding: 4px 5px;
        }

        .el-tree {
            background: #f5f5f5;
        }

        .left-box {
            position: relative;
            height: 100%;
            width: 100%;

            .el-tree-node__children {
                overflow: initial;
            }
        }

        .exp-add-exp {
            z-index: 2000;
            position: absolute;
            left: 0;
            bottom: 0;
            height: 40px;
            width: 100%;
            background: #ffffff;
            cursor: pointer;
            color: #909399;
            display: flex;
            align-items: center;
            justify-content: center;

            i {
                color: #909399;
                font-size: 20px;
                margin-right: 5px;
            }
        }

        .el-tree-node__content {
            position: relative;
            height: 32px;
        }

        .tree-node-span {
            margin-left: -10px;
            display: block;
            align-items: center;
            padding: 4px 10px;
            width: 90%;
            border-radius: 4px;
            border: 1px solid #f5f5f5;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        .node-span-wrap {
            width: 100%;
        }

        .is-component:hover {
            border: 1px solid #999;
            background-color: #fff;
        }

        .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
            background: #ecf5ff;
        }

        .iconfont {
            color: #2680eb;
            margin-right: 5px;
        }

        .scroll-bar {
            position: absolute;
            width: 100%;
            top: 50px;
            bottom: 0px;
            overflow-x: hidden;
            overflow-y: auto;
        }
    }

    .exp-item-mid {
        position: relative;
        width: 70%;
        overflow: hidden;
        background: #ffffff;
        border-left: 1px solid #dcdfe6;
        border-right: 1px solid #dcdfe6;
        .loading-box-wrap {
            height: 100%;
            .el-loading-mask {
                top: 40px;
            }
        }

        .el-tabs--border-card {
            height: 100%;
            box-shadow: none;
            border: none;

            .el-tab-pane {
                height: 100%;
            }

            .el-tabs__content {
                padding: 10px;
                height: calc(100% - 40px);
                overflow: hidden;
            }
        }
    }

    .exp-item-right {
        width: 20%;
        position: relative;
        display: flex;
        .right-empty-box {
            width: calc(100% - 30px);
            height: 100%;
        }
        .sider-right-box {
            width: 30px;
            background: #E6E6E6;
            .sider-right-box-text {
                cursor: pointer;
                width: 30px;
                font-size: 13px;
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                border-bottom: 1px solid #d9d9d9;
                padding: 16px 0px;
                i {
                    font-size: 14px;
                    color: #3a3a3a;
                    margin-bottom: 5px;
                }

                span {
                    white-space: pre-wrap;
                    color: #3a3a3a;
                    text-align: center;
                    width: 13px;
                }
                &:hover {
                    i, span {
                        color: #2680eb;
                    }
                }
            }
            .right-active {
                background: #f5f5f5;
                i, span {
                    color: #2680eb;
                }
            }
        }
        .toggle-btn {
            z-index: 2002;
            border-left: 1px solid #dcdfe6;
            display: flex;
            align-items: center;
            justify-content: center;
            background: #f5f5f5;
            cursor: pointer;
            position: absolute;
            left: -15px;
            top: 300px;
            width: 15px;
            height: 75px;
            border-top-left-radius: 15px;
            border-bottom-left-radius: 15px;
            i {
                font-size: 20px;
                color: #999;
            }
        }
    }

    .component-list {
        height: 100%;

        .el-tree {
            z-index: 2000;
            background: #f5f5f5;
        }

        .el-tree-node__content {
            height: 32px;
        }

        .tree-node-icon {
            padding-right: 5px;
            color: #2680eb;
        }
    }

    .no-exp {
        width: 200px;
        display: block;
        margin-bottom: 10px;
    }
}
</style>
